/*
 *
 *  Copyright (C) 2009 GSyC/LibreSoft
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Author : Roberto Calvo Palomino <rocapal@gsyc.es>
 *
 */

package com.LibreGeoSocial.Api;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.LibreGeoSocial.App.Home;
import com.LibreGeoSocial.App.Utils.BitmapUtils;
import com.LibreGeoSocial.App.Utils.ClientHttpRequest;
import com.LibreGeoSocial.App.Perfil.Answer;
import com.LibreGeoSocial.App.Perfil.AnswerServer;
import com.LibreGeoSocial.App.Perfil.ProfileInformation;
import com.LibreGeoSocial.App.Perfil.Question;
import com.LibreGeoSocial.App.Perfil.QuestionHandler;
import com.LibreGeoSocial.App.Perfil.Response;


public class LibreGeoSocial {

	
	private static LGSCookie sessionCookie;
	
	private static TrustManager[] trustManagers;
	
	/* TAG for log messages*/
	static private String TAG = "LibreGeoSocial";
	
	/* Singleton */
	static private LibreGeoSocial singleton = null;
	
	/* Format that server answer*/
	private String mFormat = "JSON";
	
	/* Url from server: Ex: test.libregeosocial.libresoft.es/social/ */
	private String mUrl = null;
	
	private String mUrlHttps = null;
	
	/* Cookies for connection */
	private LGSCookieStore cookieStore;
	
	/* Message from last petition */
	private String lastMsg = null;
	
	/* Code from last petition */
	private Integer lastCode = 0;
	
	/* Id for last node uploaded */
	private Integer lastId = 0;
	
	private User mUser = null;
	
	/* Photos paginacion */
	private static Integer mpagePhoto = 1;
	
	/* Notes pagination */
	private static Integer mpageNote = 1;
	
	
	private ArrayList<GeoNode> mUserList = null;
	
	private ArrayList<GeoNode> mFriendList = null;
	
	static public LibreGeoSocial getInstance() 
	{
        if (singleton == null) {
            singleton = new LibreGeoSocial();
        }
        return singleton;
		
	}
	
	public void setFormat (String format)
	{
		
		if ( format.compareTo("JSON") != 0 && format.compareTo("XML") != 0) 
		{
			Log.e("TAG", "Unknow format\n");
		}
		
		mFormat = format;
		
	}
	
	public String getUrlServer ()
	{
		return mUrl;
	}
	
	public void setUrl (String Url)
	{
		mUrl = "http://" + Url;
		mUrlHttps = "https://" + Url;
	}
	
	public String getLastMsgServer()
	{		
		return "[" + lastCode.toString() + "]: " + lastMsg;
	}
	
	public Integer getLastId ()
	{
		return lastId;
	}
	
	
    /**
     * Do user register in the server.
     * 
     * @param User object with info user.
     * 
     * @return Boolean variable operation
     */
	
	public boolean registerUser (User user)
	{
		try {            
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost = new HttpPost(mUrl + "user/create/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("username", user.getUsername()));		
		    nvps.add(new BasicNameValuePair("password", user.getPassword()));
		    nvps.add(new BasicNameValuePair("first_name", user.getName()));
		    nvps.add(new BasicNameValuePair("last_name", "" ));
		    nvps.add(new BasicNameValuePair("email", user.getEmail() ));
		    nvps.add(new BasicNameValuePair("latitude", user.getLatitude().toString() ));
		    nvps.add(new BasicNameValuePair("longitude", user.getLongitude().toString() ));
		    nvps.add(new BasicNameValuePair("radius", user.getRadius().toString() ));
		    nvps.add(new BasicNameValuePair("country", user.getCountry() ));
		    //nvps.add(new BasicNameValuePair("post_code", user.getPostCode().toString() ));
		    //nvps.add(new BasicNameValuePair("birthday", user.getBirthday() ));
		    
			
		    
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
    
		    HttpResponse response = httpclient.execute(httpost);
		    
		    HttpEntity entity = response.getEntity(); 
		    
            String str = convertStreamToString(entity.getContent());
            
            
            return processMessage(str);
            
		} catch (IOException e) {
	        // TODO Auto-generated catch block
	        Log.e(TAG,e.getMessage());
	        return false;
		}
	
	}
	
	
    /**
     * Do login with server. If login is ok, the session cookie is saved
     * 
     * @param username The username
     * @param password The password
     * 
     * @return Boolean
     */
	
	public boolean login (String username, String password) 
	{
		HttpsURLConnection urlConn;
		URL url;
		
        try {      
        	
        	
        	String secureURL = mUrlHttps + "user/login/?format=JSON";
			        	
        	allowAllSSL();
        	
        	url = new URL(secureURL);
			
			urlConn = (HttpsURLConnection) url.openConnection();
			
			// set Post method
	        urlConn.setDoOutput (true);
	        
	        // setting headers
	        urlConn.setRequestMethod("POST");
	        urlConn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");       
	        urlConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
	        urlConn.setRequestProperty("Host", "login.facebook.com");  
            urlConn.setRequestProperty("Connection", "Keep-Alive");
			
			// making content
	        String data = "username=" + username + 
	        				"&password="+ password;
	        

	        // writing content
			OutputStreamWriter out = new OutputStreamWriter(urlConn.getOutputStream());
			out.write (data);
			out.flush();
			
			// getting response
			
			InputStream in = urlConn.getInputStream();
						
			String str = convertStreamToString(in);
			
			Log.e(TAG,str);

			if ( processMessage(str) )
			{
				String headerName;
				
				/* Search cookie */
				for (int i=1; (headerName = urlConn.getHeaderFieldKey(i))!=null; i++) {
					if (headerName.equals("set-cookie")) { 
						
						/* Parse the cookie */
						String cookieStr = urlConn.getHeaderField(i);

						cookieStr = cookieStr.substring(0, cookieStr.indexOf(";"));
					    String cookieName = cookieStr.substring(0, cookieStr.indexOf("="));
					    String cookieValue = cookieStr.substring(cookieStr.indexOf("=") + 1, cookieStr.length()); 
					    
					    /* Generate our cookie */
			        	
					    sessionCookie = new LGSCookie();					    
					    sessionCookie.setDomain(mUrl.split("/")[2]);
					    sessionCookie.setName(cookieName);
					    sessionCookie.setValue(cookieValue);
					    
					    cookieStore = new LGSCookieStore();
					    cookieStore.addCookie(sessionCookie);
					    
					}
				}
				
				return true;
			}
            else
            	return false;
        	
		    
		} catch (IOException e) {
		        // TODO Auto-generated catch block
 		        Log.e(TAG,e.getMessage());
		        return false;
		}
		
	}

	
	public ArrayList<GeoNode> getLayerNodes (String layer, String pattern, String category, Double distance, Integer page, Integer elems)
	{
	
		
		try
		{
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
		

			if (pattern==null)
				pattern = "";
			Log.i("PetitionURL", mUrl +  "layer/" + layer + 
					   "/search/?search=" + pattern + 
					   "&category=" + category +
					   "&latitude=" + String.valueOf(Home.currentLocation.getLatitude()) + 
					   "&longitude=" + String.valueOf(Home.currentLocation.getLongitude()) + 
					   "&page=" + page.toString() +
					   "&elems=" + elems.toString() +
					   "&radius=" + distance.toString() + "&format=JSON");
			httpost = new HttpPost(mUrl +  "layer/" + layer + 
								   "/search/?search=" + pattern + 
								   "&category=" + category +
								   "&latitude=" + String.valueOf(Home.currentLocation.getLatitude()) + 
								   "&longitude=" + String.valueOf(Home.currentLocation.getLongitude()) + 
								   "&page=" + page.toString() +
								   "&elems=" + elems.toString() +
								   "&radius=" + distance.toString() + "&format=JSON");
							
			Log.e("LGS-getLayerNodes:", mUrl +  "layer/" + layer + 
								   "/search/?search=" + pattern + 
								   "&category=" + category +
								   "&latitude=" + Home.currentLocation.getLatitude() + 
								   "&longitude=" + Home.currentLocation.getLongitude() + 
								   "&page=" + page.toString() +
								   "&elems=" + elems.toString() +
								   "&radius=" + distance.toString() + "&format=JSON");
		
		
			
			httpclient.setCookieStore(cookieStore);
						

			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
	        ArrayList<GeoNode> array = new ArrayList<GeoNode>();
	        ArrayList<GeoNode> aux = null;
	        
	        aux = parseNotes (str,distance);
	        if (aux!=null)
	        	array.addAll (aux);
	        
	        aux = parsePhotos (str,distance);
	        if (aux!=null)
	        	array.addAll (aux);
	        
	        aux = parseAudios (str, distance);
	        if (aux!=null)
	        	array.addAll (aux);
	       
	        aux = (parseUsers(str, distance));
	        if (aux!=null)
	        	array.addAll (aux);
	        
	        Log.e("LGS: size array=",String.valueOf(array.size()));
	 
	        return array;
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	

    /**
     * Return all users in the server
     * 
     * @param reaload If is false, data obtains of cache.
     * @param distance The maximum distance of users
     * 
     * @return The user list in array list.
     */
	
	public ArrayList<GeoNode> getUserList (boolean reload, Double distance, String pattern, Integer page)
	{
	
		if (reload == false && mUserList != null)
			return mUserList;
		
		try
		{
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			if (distance == 0.0)
				 httpost = new HttpPost(mUrl + "user/list/?page=" + page.toString() + "&format=JSON"); 
			else
			{
				if (pattern==null)
					pattern = "";
				httpost = new HttpPost(mUrl +  "search/?terms=" + pattern + "&dist=" + distance.toString() + "&models=person&format=JSON"); 
			}
			//HttpGet httpget = new HttpGet(mUrl + "user/list/?format=JSON"); 
			
			httpclient.setCookieStore(cookieStore);
						

			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
	        mFriendList = parseUsers(str,distance);
	        return mFriendList;
			
        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	
    /**
     * Return all friends of login user.
     * 
     * @param reaload If is false, data obtains of cache.
     * 
     * @return The friend list in array list.
     */
	
	public ArrayList<GeoNode> getFriendsList (boolean reload, Double distance, Integer page)
	{
		if (reload == false && mFriendList != null)
			return mFriendList;
		
		try
		{
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/" + mUser.getId().toString() + "/friends/?page=" + page.toString() +  "&format=JSON"); 
			
			nvps.add(new BasicNameValuePair("elems", String.valueOf(15)));
			httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
        
	        
	        mFriendList = parseUsers(str, distance);
	        return mFriendList;
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		

	}
	
    /**
     * Return the GeoNode updated
     * @param node The node we want updated
     * 
     * @return The GeoNode
     */
	public GeoNode updateNode (GeoNode node)
	{

		String token = null;
		
		if ( Photo.class.isInstance(node) )    	
			token = "photo";
		else if (Note.class.isInstance(node) )
			token = "note";
		else if (User.class.isInstance(node) )
			token = "user";
		else if (Audio.class.isInstance(node) )
			token = "audio";
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpGet httpGet = new HttpGet(mUrl + token + "/" + node.getId().toString() + "/data/?format=JSON");						
						  
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpGet);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return parseNode(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	
	private GeoNode parseNode (String str)
	{
		
		JSONObject json;

        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
			
			if (lastCode==200)
			{					
				if (json.has("user"))
				{
					JSONObject jsonUser = json.getJSONObject("user");
					return (GeoNode) parseUser(jsonUser);
				}
				else if (json.has("photo"))
				{
					JSONObject jsonPhoto = json.getJSONObject("photo");
					return (GeoNode) parsePhoto(jsonPhoto);
				}
				else if (json.has("note"))
				{
					JSONObject jsonNote = json.getJSONObject("note");
					return (GeoNode) parsePhoto(jsonNote);
				}
				else if (json.has("audio"))
				{
					JSONObject jsonAudio = json.getJSONObject("audio");
					return (GeoNode) parsePhoto(jsonAudio);
				}
				else 
				{
					lastMsg = "parseNode:: Error, Node type unknown!";
					return null;
				}
				
			}
			else
			{
				lastMsg = json.getString("description");
				return null;					
			}
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.getMessage());
			return null;
		}
		
	}
	

	
    /**
     * Return the friendship invitations
     *  
     * 
     * @return The user info
     */
	
	public ArrayList<GeoNode> getFrienshipInvitations ()
	{
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpGet httpGet = new HttpGet(mUrl + "user/friendship_invitations/?format=JSON");						
						  
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpGet);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return parseUsers(str,0.0);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
		
	}
	
	
    /**
     * Return the info user
     * 
     * @param reaload If is false, data obtains of cache.
     * @param userId The identifier of user 
     * 
     * @return The user info
     */
	
	public User getInfoUser (boolean reload, Integer userId)
	{
		
		if ( reload == false && mUser != null)
			return mUser;
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpget = null;
			
			if (userId==null)
				httpget = new HttpPost(mUrl + "user/my_data/?format=JSON");
			else
				httpget = new HttpPost(mUrl + "user/" + userId.toString() + "/data/?format=JSON");
			
			
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpget);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
            JSONObject json;

            try {
				json = new JSONObject(str);
				lastCode = json.getInt("code");
				if (lastCode==200)
				{					
					JSONObject jsonUser = json.getJSONObject("user");
					
					User infoUser = (User) parseUser(jsonUser);
					
					if (userId==null)
					{
						mUser = infoUser;
						return mUser;						
					}
					else
						return infoUser;
					
				}
				else
				{
					lastMsg = json.getString("description");
					return null;					
				}
				
			} catch (JSONException e) {	
				lastCode = 500;
				lastMsg = "Error in json parsed: " + e.getMessage();
				Log.e(TAG, e.getMessage());
				return null;
			}
			
        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	public boolean setAvatar( Integer photoId )
	{
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/set_avatar/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("photo_id", photoId.toString() )); 
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 		    
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return processMessage(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
    /**
     * Set the status of user.
     * 
     * @param status Text of the status
     * 
     * @return Boolean
     */
	
	public boolean setStatus (String status)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/set_status/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("status", status )); 
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 		    
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return processMessage(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
    /**
     * Set friend of the user
     * 
     * @param idFriend Identifier of friend
     * 
     * @return Boolean variable
     */
	
	public boolean setFriend (Integer idFriend)
	{
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/relation/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("userid1", mUser.getId().toString() )); 
		    nvps.add(new BasicNameValuePair("userid2", idFriend.toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 		    
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return processMessage(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
		
	}
	
    /**
     * Delete a relation of friend
     * 
     * @param idFriend Identifier of friend
     * 
     * @return Boolean variable
     */
	public boolean deleteFriend (Integer idFriend)
	{
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/relation/delete/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("userid1", mUser.getId().toString() )); 
		    nvps.add(new BasicNameValuePair("userid2", idFriend.toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 		    
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return processMessage(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
		
	}
	
    /**
     * Set an user geo-position 
     * 
     * @param latitude latitude coordenate
     * @param longitude longitude coordenate
     * 
     * @return Boolean variable
     */
	public boolean setUserPosition (Double latitude, Double longitude, Double altitude)
	{

		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/position/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("latitude", latitude.toString()));
		    nvps.add(new BasicNameValuePair("longitude", longitude.toString()));
		    nvps.add(new BasicNameValuePair("altitude", altitude.toString()));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
	        return processMessage(str);
	                
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
    /**
     * Create and upload note to server 
     * 
     * @param note It's a note objetc.     
     * 
     * @return Boolean variable
     */	
	public boolean createNote (Note note)
	{
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "note/create/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			nvps.add(new BasicNameValuePair("title", note.getTitle()));
			nvps.add(new BasicNameValuePair("text", note.getBody()));
		    nvps.add(new BasicNameValuePair("latitude", note.getLatitude().toString()));
		    nvps.add(new BasicNameValuePair("longitude", note.getLongitude().toString() ));
		    nvps.add(new BasicNameValuePair("altitude", note.getAltitude().toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
	        return processMessage(str);
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
	}
	
	public boolean deleteNote (Integer noteId)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			httpost = new HttpPost(mUrl + "note/delete/?format=JSON"); 

			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			nvps.add(new BasicNameValuePair("noteid", noteId.toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return processMessage(str);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
	public boolean deleteSound (Integer noteId)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			httpost = new HttpPost(mUrl + "sound/delete/?format=JSON"); 

			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			nvps.add(new BasicNameValuePair("soundid", noteId.toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return processMessage(str);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
	public void setPageNote (Integer pageNote)
	{
		mpageNote = pageNote;
	}
	
    /**
     * Get all notes geo-located     
     * 
     * @return Return all notes in Array List
     */
	public ArrayList<GeoNode> getNotes (Double distance, String pattern)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost;
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
			if (distance == 0.0)
			{
				 httpost = new HttpPost(mUrl + "note/list/?format=JSON"); 
				 nvps.add(new BasicNameValuePair("page", mpageNote.toString()));
			}
			else
			{
				if (pattern==null)
					pattern = "";
				
				httpost = new HttpPost(mUrl +  "search/?terms=" + pattern + "&dist=" + distance.toString() + "&models=note&format=JSON"); 			
			}
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        

			return parseNotes(str, distance);	
  
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
	}
	
	
	   /**
     * Get all notes geo-located     
     * 
     * @return Return all notes in Array List
     */
	public ArrayList<GeoNode> getAudios (Double distance, String pattern)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost;

			httpost = new HttpPost(mUrl +  "search/?terms=" + pattern + "&dist=" + distance.toString() + "&models=sound&format=JSON"); 			
				 
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        

			return parseAudios (str, distance);	
  
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
	}	
	
	public boolean uploadPhoto (Photo photo)
	{
		
		try
		{

			ClientHttpRequest myclient = new ClientHttpRequest( mUrl + "photo/upload/?format=JSON");
			
			myclient.setHeader( "Cookie" ,
								cookieStore.getCookies().get(0).getName() + "=" + 
							    cookieStore.getCookies().get(0).getValue());
			
			
			Log.e(TAG,cookieStore.getCookies().get(0).getName());
			Log.e(TAG,cookieStore.getCookies().get(0).getValue());
			
			InputStream serverInput = myclient.post (
														new Object[] {
															"latitude", photo.getLatitude().toString(),
										                    "longitude", photo.getLongitude().toString(),
										                    "altitude", photo.getAltitude().toString(),
										                    "name", photo.getName(),
										                    "description" , photo.getDescription(),
										                    "photo", new File(photo.getUrl()) 
														}
													 );                   
			
			BufferedReader in = new BufferedReader(new InputStreamReader(serverInput));
			
			String inputLine;			
			String reponseString = "";
			
			while ((inputLine = in.readLine()) != null) {
				Log.e(TAG,"EPPP:" + inputLine);
				reponseString = reponseString + inputLine;
			}
			

	        Log.e(TAG, reponseString);
	        
	        return processMessage(reponseString);

		}
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
	public boolean uploadAudio (Audio audio)
	{
		
		try
		{

			ClientHttpRequest myclient = new ClientHttpRequest( mUrl + "sound/upload/?format=JSON");
			
			myclient.setHeader( "Cookie" ,
								cookieStore.getCookies().get(0).getName() + "=" + 
							    cookieStore.getCookies().get(0).getValue());
			
			
			Log.e(TAG,cookieStore.getCookies().get(0).getName());
			Log.e(TAG,cookieStore.getCookies().get(0).getValue());
			
			InputStream serverInput = myclient.post (
														new Object[] {
															"latitude", 	audio.getLatitude().toString(),
										                    "longitude", 	audio.getLongitude().toString(),
										                    "altitude", 	audio.getAltitude().toString(),
										                    "name", 		audio.getName(),
										                    "description" , audio.getDescription(),
										                    "sound", 		new File(audio.getPath() ) 
														}
													 );                   
			
			BufferedReader in = new BufferedReader(new InputStreamReader(serverInput));
			
			String inputLine;			
			String reponseString = "";
			
			while ((inputLine = in.readLine()) != null) {
				Log.e(TAG,"EPPP:" + inputLine);
				reponseString = reponseString + inputLine;
			}
			

	        Log.e(TAG, reponseString);
	        
	        return processMessage(reponseString);

		}
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
	public boolean deletePhoto (Integer photoId)
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			httpost = new HttpPost(mUrl + "photo/delete/?format=JSON"); 

			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			nvps.add(new BasicNameValuePair("photoid", photoId.toString() ));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return processMessage(str);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
	}
	
	public boolean setPrivacyNode (Integer nodeId, String privacyLevel, Boolean updateLocation)
	{
		Log.e("SetPrivacyNode","nodeId: " + nodeId.toString() + " privacy: " + privacyLevel);
		Log.e("SetPrivacyLocation: ", updateLocation.toString());
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			httpost = new HttpPost(mUrl + "node/" + nodeId.toString() + "/privacy/change/?format=JSON"); 

			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
			if (updateLocation)
				nvps.add(new BasicNameValuePair("field", "position"));
			
			nvps.add(new BasicNameValuePair("perm", privacyLevel));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return processMessage(str);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
		
		
	}
	
	public InputStream getAudio (String url)
	{
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
	
			HttpPost httpost = new HttpPost(url);
			
			/* create cookie */
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();			
			httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);
	
			/* Send and receive the petition */
			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
		    return entity.getContent();
		   	
		    
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
	}
	
	
	public Bitmap getBitmap (String url)
	{
		final int IO_BUFFER_SIZE = 4 * 1024;
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
	
			HttpPost httpost = new HttpPost(mUrl + url);
			
			Log.e("getBitMap:",mUrl + url);
			
			/* create cookie */
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();			
			httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));	
			httpclient.setCookieStore(cookieStore);
	
			/* Send and receive the petition */
			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
		    InputStream in = entity.getContent();
		    
		    /* Convert response to bitmap */
            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            BufferedOutputStream out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
            BitmapUtils.copy(in, out);
            out.flush();
            
            final byte[] data = dataStream.toByteArray();
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
	        
            return bitmap;
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
	}
	
	public ArrayList<GeoNode> getMyPhotos ()
	{
	
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			httpost = new HttpPost(mUrl + "user/" + mUser.getId().toString() + "/photos/?format=JSON"); 

			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore);

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return parsePhotos(str, 0.0);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	public void setPagePhoto (Integer pagePhoto)
	{
		mpagePhoto = pagePhoto;
	}
	
    /**
     * Get photos of server. Two modes: search by distance or search by pattern
     * 
     * @param distance The max distance by search the nodes
     * @param pattern The string pattern by search the nodes.
     * 
     * @return All the nodes
     */
	
	public ArrayList<GeoNode> getPhotos (Double distance, String pattern )
	{
	
		
		try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			HttpPost httpost;
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
			
			if (distance == 0.0)
			{
				 httpost = new HttpPost(mUrl + "photo/list/?format=JSON"); 
				 nvps.add(new BasicNameValuePair("page", mpagePhoto.toString()));				 
			}
			else
			{
				if (pattern==null)
					pattern = "";
				httpost = new HttpPost(mUrl +  "search/?terms=" + pattern + "&dist=" + distance.toString() +  "&models=photo&format=JSON"); 
				Log.e("LGS",mUrl +  "search/?terms=" + pattern + "&dist=" + distance.toString() +  "&models=photo&format=JSON");
			}			
			
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));		    		    
			httpclient.setCookieStore(cookieStore); 

			HttpResponse response = httpclient.execute(httpost);
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);

	        return parsePhotos(str,distance);
	        
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
		
	}
	
	
	public Question getQuestion(){
		Question question = new Question();
		String urlServerQuestion = mUrl;
    	if (mFormat.equals("JSON")){
    		try {
    			DefaultHttpClient httpclient = new DefaultHttpClient();
            	httpclient.setCookieStore(cookieStore);
                // Prepare a request object
            	urlServerQuestion += "question/getquestion/?format=json";
                HttpGet httpget = new HttpGet(urlServerQuestion); 
                // Execute the request
                HttpResponse response;
                response = httpclient.execute(httpget);
                // Get hold of the response entity
                HttpEntity entity = response.getEntity();
                // If the response does not enclose an entity, there is no need
                // to worry about connection release
                if (entity != null) {
                    // A Simple JSON Response Read
                    InputStream instream = entity.getContent();
                    String result= convertStreamToString(instream);
                    // A Simple JSONObject Creation
                    JSONObject object = new JSONObject(result);
                    question = new Question();
                    //parse JSONObject
                    int code = object.getInt(ProfileInformation.CODE);
                    question.setCode(code);
            		if (code == ProfileInformation.OK){
            			lastCode = code;
            			JSONObject qdescriptor = object.getJSONObject(ProfileInformation.QDESCRIPTOR);
            			JSONArray proposal = qdescriptor.getJSONArray(ProfileInformation.PROPOSAL);
            			for (int i=0; i<proposal.length();i++){
            				JSONObject objectI = proposal.getJSONObject(i);
            				JSONObject answerJS = objectI.getJSONObject(ProfileInformation.ANSWER);
            				question.addAnswer(new Answer(answerJS.getString(ProfileInformation.TEXT),
            						answerJS.getInt(ProfileInformation.CODE)));
            			}
            			JSONObject questionJS = qdescriptor.getJSONObject(ProfileInformation.QUESTION);
            			question.setIdentifier(questionJS.getInt(ProfileInformation.IDENTIFIER));
            			question.setTopic(questionJS.getString(ProfileInformation.TOPIC));
            			question.setText(questionJS.getString(ProfileInformation.TEXT));
            			question.setType(questionJS.getString(ProfileInformation.TYPE));
            			question.setStatus(Question.RIGTH);
            		} else{
            			question.setErrorDescription(object.getString(ProfileInformation.DESCRIPTION));
            			question.setStatus(Question.ERROR);
            		}
     
                    // Closing the input stream will trigger connection release
                    instream.close();
                }
    		} catch (IOException e){
    			lastCode = 500;
    			lastMsg = "Error in json parsed: " + e.getMessage();
    			Log.e(TAG,e.getMessage());
    			return question;
            } catch (JSONException e){
            	lastCode = 500;
    			lastMsg = "Error in json parsed: " + e.getMessage();
            	Log.e(TAG,e.getMessage());
            	return question;
            }
    	}
    	else {// read question XML
    		try {
    			urlServerQuestion += "question/getquestion/";
    			URL url = new URL(urlServerQuestion);
        		SAXParserFactory spf = SAXParserFactory.newInstance();
        		SAXParser sp = spf.newSAXParser();
        		XMLReader xr = sp.getXMLReader();
        		/* Create a new ContentHandler and apply it to the XML-Reader*/
        		QuestionHandler myQuestionHandler = new QuestionHandler();
        		xr.setContentHandler(myQuestionHandler);
        		/* Parse the xml-data from our URL. */
        		xr.parse(new InputSource(url.openStream()));
        		/* Parsing has finished. */
        		question = myQuestionHandler.getParseQuestion();
        		lastCode = 200;
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				lastCode = 500;
				lastMsg = "Error in xml parsed: " + e.getMessage();
				Log.e(TAG,e.getMessage());
            	return question;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				lastCode = 500;
				lastMsg = "Error in xml parsed: " + e.getMessage();
				Log.e(TAG,e.getMessage());
            	return question;
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				lastCode = 500;
				lastMsg = "Error in xml parsed: " + e.getMessage();
				Log.e(TAG,e.getMessage());
            	return question;
			}
    		
    	}
    	
    	return question;
	}
	
	public AnswerServer sendResponse(Response response){
		AnswerServer as = new AnswerServer();
		String urlServerResponse = mUrl+"question/sendanswer/";
		if (mFormat.equals("JSON")) urlServerResponse += "?format=JSON";
		try {
			DefaultHttpClient httpclient = new DefaultHttpClient();
			httpclient.setCookieStore(cookieStore);
			HttpPost httpost = new HttpPost(urlServerResponse);
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("question_id", Integer.toString(response.getQuestion_id())));		
		    //nvps.add(new BasicNameValuePair("email", response.getMail()));
		    //nvps.add(new BasicNameValuePair("language", ""));
		    nvps.add(new BasicNameValuePair("comment", response.getComment()));
		    nvps.add(new BasicNameValuePair("answers", response.getAnswers_idArray()));
		    
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
		    HttpResponse hr = httpclient.execute(httpost);
		    
		    HttpEntity entity = hr.getEntity(); 
		    
	        String strAnswerServer = convertStreamToString(entity.getContent());
	        Log.e(TAG,"-->Answer-Response: " + strAnswerServer);
	        if (mFormat.equals("JSON")){            
		    	try {
		    		JSONObject object = new JSONObject(strAnswerServer);
		    		Log.e(TAG,"-->JSON-Response: " + object.toString());
		    		as.setCode(object.getInt(ProfileInformation.CODE));
		    		JSONObject operation = object.getJSONObject(ProfileInformation.OPERATION);
		    		as.setMessage(operation.getString(ProfileInformation.MESSAGE));
		    		as.setResult(operation.getString(ProfileInformation.RESULT));
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					Log.e(TAG,e.getMessage());
					lastCode = 500;
					as.setCode(500);
					as.setMessage(e.getMessage());
					lastMsg = "Error in response parsed: " + e.getMessage();
					return as;
				}
			}
			else {
				SAXParserFactory spf = SAXParserFactory.newInstance();
        		SAXParser sp = spf.newSAXParser();
        		XMLReader xr = sp.getXMLReader();
        		/* Create a new ContentHandler and apply it to the XML-Reader*/
        		QuestionHandler myQuestionHandler = new QuestionHandler();
        		xr.setContentHandler(myQuestionHandler);
        		xr.parse(strAnswerServer);
        		as = myQuestionHandler.getAnswerServer();
			}
		} catch (Exception e){
			Log.e(TAG,e.getMessage());
			as.setCode(500);
			as.setMessage(e.getMessage());
			lastCode = 500;
			lastMsg = "Error in response parsed: " + e.getMessage();
			return as;
		}
		lastCode = 200;
		return as;
	}
	
    private String convertStreamToString (InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8*1024);
        StringBuilder sb = new StringBuilder();
 
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        return sb.toString();

    }
	
	
    /*
     * Privacy
     * 
     * */
    
    public static String PRIVACY_PUBLIC 			= "Public";
    public static String PRIVACY_FRIENDS_OF_FRIENDS = "Friends of friends";
    public static String PRIVACY_FRIENDS 			= "Friends";
    public static String PRIVACY_PRIVATE			= "Private";
   
    
    public boolean setProfilePrivacy (String privacyLevel)
    {
    
		try
		{
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/privacy/change/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("perm", privacyLevel));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
	        return processMessage(str);
	                
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
    	
    }
    
    public boolean setLocationPrivacy (String privacyLevel)
    {
    
		try
		{
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "user/privacy/allow/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("field", "position"));
		    nvps.add(new BasicNameValuePair("role", privacyLevel));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
	        return processMessage(str);
	                
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
    	
    }
    
    public boolean setTags (Integer id, String tags)
    {
    	
		try
		{
			
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpPost httpost = new HttpPost(mUrl + "node/" + id.toString() + "/tag/?format=JSON"); 
			
			List <NameValuePair> nvps = new ArrayList <NameValuePair>();
		    nvps.add(new BasicNameValuePair("tags", tags));
			
		    httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); 
		    
			httpclient.setCookieStore(cookieStore);
			HttpResponse response = httpclient.execute(httpost);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());	        
	        
	        Log.e(TAG, str);
	        
	        return processMessage(str);
	                
		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return false;
		}
    	
    }
    
    public ArrayList<Group> getMyGroups ()
    {
    	
    	try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpGet httpGet = new HttpGet(mUrl + "user/groups/?format=JSON");						
						  
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpGet);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return parseGroups(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
    	
    }
    
    public ArrayList<GeoNode> sematingSearch (String pattern)
    {
    	try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();						
				
			HttpGet httpGet = new HttpGet(mUrl.split("/")[0] + "/semanticSearch/social/search/semantic/?word=" + pattern + "&format=JSON");						
						  
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpGet);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return parseElementsGroup(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
    	
    }
    
    public ArrayList<GeoNode> getElementsGroup (Integer groupId)
    {
    	
    	try
		{
			DefaultHttpClient httpclient = new DefaultHttpClient();
			
			HttpGet httpGet = new HttpGet(mUrl + "group/" + groupId.toString() + "/elements/?format=JSON");						
						  
			httpclient.setCookieStore(cookieStore);
			
			HttpResponse response = httpclient.execute(httpGet);
	
		    HttpEntity entity = response.getEntity(); 
		    
	        String str = convertStreamToString(entity.getContent());
	        
	        Log.e(TAG, str);
	        
            return parseElementsGroup(str);

		}
		
		catch (IOException e) {
	        Log.e(TAG,e.getMessage());
	        return null;
		}
    }
    
    public ArrayList<GeoNode> searchAllNodes (Double distance, String pattern )
    {
    	
    	ArrayList<GeoNode> sNodes;
    	
    	sNodes = this.getPhotos(distance, pattern);
    	sNodes.addAll( this.getNotes(distance, pattern) );
    	//sNodes.addAll( this.getAudios(distance, pattern) );
    	sNodes.addAll( this.getUserList(true,distance, pattern, 1) );
    	
    	
    	return sNodes;
    }
    
	private boolean processMessage (String str)
	{
		
        try {
        	JSONObject json;
			json = new JSONObject(str);
			lastCode = json.getInt("code");
			lastMsg  = json.getString("description");
			
			if (json.has("id"))
				lastId = json.getInt("id");
			else
				lastId = -1;
			
			if (lastCode != 200)
				return false;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return false;
		}
		
		return true;
		
	}
	
	
	private ArrayList<GeoNode> parseElementsGroup (String str)
	{
		
		JSONObject json;
		ArrayList<GeoNode> list = new ArrayList<GeoNode>();
		
		 
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode==200)
			{					
				JSONObject object = null;
				
				// HACK: This method works with elements groups and semantic search results
				if (json.has("elements"))
					object = json.getJSONObject("elements");
				
				else if (json.has("results"))
					object = json.getJSONObject("results");
				
				// Parse photos
				if (object.has("photo"))
				{
					JSONArray array = object.getJSONArray("photo");
					
					for (int i = 0; i < array.length(); i++) 
					{					
						JSONObject obj = array.getJSONObject(i);		
						list.add( parsePhoto(obj));
					}
					
				}
				// Parse persons	
				if (object.has("person"))
				{
					JSONArray array = object.getJSONArray ("person");
					
					for (int i = 0; i < array.length(); i++) 
					{ 
						
						User user = (User) parseUser (array.getJSONObject(i));			
						
						if (user.getId() == mUser.getId())
							continue;
						
						list.add(user);
						
					}
				}
				
				// Parse notes		
				if (object.has("note"))
				{
					JSONArray array = object.getJSONArray ("note");
					
					for (int i = 0; i < array.length(); i++) 
					{ 				
						JSONObject obj = array.getJSONObject(i);	
						list.add( parseNote(obj));				
					}
					
				}
				return list;
			}
			
			return null;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}
	  							
	}
	
	
	private ArrayList<Group> parseGroups (String str)
	{
		
		JSONObject json;
        
        ArrayList<Group> list = new ArrayList<Group>();
        
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode==200)
			{					
				JSONArray array = json.getJSONArray("groups");
				
				String groupName, since, since_position, groupType;
				Double latitude, longitude, altitude, radius;	
				Integer id = 0;
				
				for (int i = 0; i < array.length(); i++) 
				{
					since_position = "";
					latitude = longitude = radius = altitude = -1.0;
					
					JSONObject obj = array.getJSONObject(i);
										
					id = obj.getInt("id");
					groupName = obj.getString("groupname");
					groupType = obj.getString("type");	
					
					if (obj.has("since"))
						since = obj.getString("since");
					
					if (obj.has("position"))
					{
						JSONObject objPosition = obj.getJSONObject("position");
						
						latitude = objPosition.getDouble("latitude");
						longitude = objPosition.getDouble("longitude");
						altitude = objPosition.getDouble("altitude");
						
						if (objPosition.has("radius"))
							radius = objPosition.getDouble("radius");
						
						if (objPosition.has("since"))
							since_position = objPosition.getString("since");
					}
					
					Group group = new Group(id, groupName, groupType,
							                  latitude, longitude, altitude, radius, since_position);
					
					
					list.add(group);
					
				}
				
				return list;
			}
			else
			{
				lastMsg = json.getString("description");
				return null;
			}
			
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}	  
		
	}
	
	private ArrayList<GeoNode> parsePhotos (String str, Double distance)
	{
		
        JSONObject json;
        
        ArrayList<GeoNode> list = new ArrayList<GeoNode>();
        
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode != 200)
				return null;
			
			JSONArray array;
			

			JSONObject photos = json.getJSONObject("results");
			array = photos.getJSONArray("photo");
			

			for (int i = 0; i < array.length(); i++) 
			{
				
				JSONObject obj = array.getJSONObject(i);
				
				list.add( parsePhoto(obj));
			}
			
			return list;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return new ArrayList<GeoNode>();
		}	  
		
	}
	
	private Photo parsePhoto (JSONObject obj)
	{
		
		String description, since, since_position, url, name;
		Double latitude, longitude, altitude, radius;			
		
		since  = null;		
		Integer id = null;
		
		latitude = longitude = radius = altitude = -1.0;				
				
		try {
			
		
			if (obj.has("id"))
				id = obj.getInt("id");
			else
				id = 0;
			
			name = obj.getString("name");
			description = obj.getString("description");	
			
			if (obj.has("since"))
				since = obj.getString("since");
			
			if (obj.has("position"))
			{
				JSONObject objPosition = obj.getJSONObject("position");
				
				latitude = objPosition.getDouble("latitude");
				longitude = objPosition.getDouble("longitude");
				
				if (objPosition.has("altitude"))
					altitude = objPosition.getDouble("altitude");
				
				if (objPosition.has("radius"))
					radius = objPosition.getDouble("radius");
				
				if (objPosition.has("since"))
					since_position = objPosition.getString("since");
			}
		 
		
			/* If id=0 then the geonode is external, 
			 * and the image is saved in photo_url field */
			
			ExtenalInfo extInfo = null;
			url = null;
			
			if (id==0)
			{
				extInfo = new ExtenalInfo();
				
				if (obj.has("external_info"))
				{
					JSONObject objPosition = obj.getJSONObject("external_info");
					
					if (objPosition.has("info_url"))
						extInfo.setUrlInfo(objPosition.getString("info_url"));
					
					if (objPosition.has("photo_thumb"))
					{
						extInfo.setPhotoThumbUrl (objPosition.getString("photo_thumb"));
						url = extInfo.getPhotoThumbUrl();
					}
					
					if (objPosition.has("photo_url"))
						extInfo.setPhotoNormalUrl (objPosition.getString("photo_url"));
				}
				
			}
			else
				url = "photo/" + id.toString() + "/image/";
			
			Photo myPhoto = new Photo (id,latitude,longitude,altitude,radius,name,description,url,since, null);
			myPhoto.setExternalInfo (extInfo);
			
			return myPhoto;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}	 
		
	}
	
	
	
	
	
	private ArrayList<GeoNode> parseAudios (String str, Double distance)
	{
		
        JSONObject json;
        
        ArrayList<GeoNode> list = new ArrayList<GeoNode>();
        
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode != 200)
				return null;
			
			JSONArray array;

			JSONObject photos = json.getJSONObject("results");
			array = photos.getJSONArray("sound");

			

			for (int i = 0; i < array.length(); i++) 
			{
				
				JSONObject obj = array.getJSONObject(i);
				
				list.add( parseAudio(obj));
			}
			
			return list;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}	  
		
	}
	
	private Audio parseAudio (JSONObject obj)
	{
		
		String description, since, since_position, url, name;
		Double latitude, longitude, altitude, radius;			
		
		since  = null;		
		Integer id = null;
		
		latitude = longitude = radius = altitude = -1.0;				
				
		try {
			
		
			id = obj.getInt("id");
			name = obj.getString("name");
			description = obj.getString("description");	
			
			if (obj.has("since"))
				since = obj.getString("since");
			
			if (obj.has("position"))
			{
				JSONObject objPosition = obj.getJSONObject("position");
				
				latitude = objPosition.getDouble("latitude");
				longitude = objPosition.getDouble("longitude");
				altitude = objPosition.getDouble("altitude");
				
				if (objPosition.has("radius"))
					radius = objPosition.getDouble("radius");
				
				if (objPosition.has("since"))
					since_position = objPosition.getString("since");
			}
		 
		
			url = mUrl + "sound/" + id.toString() + "/file/";
			
			return new Audio (id,name,description,url,"",latitude,longitude,altitude,radius,since);
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}	 
		
	}
	
	
	
	
	
	
	private ArrayList<GeoNode> parseNotes (String str, Double distance)
	{
		
		Log.e("str: ", str);
		
        JSONObject json;
        
        ArrayList<GeoNode> list = new ArrayList<GeoNode>();
        
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode != 200)
				return null;
			
			JSONArray array;
			

			JSONObject photos = json.getJSONObject("results");
			array = photos.getJSONArray("note");

			for (int i = 0; i < array.length(); i++) 
			{
				JSONObject obj = array.getJSONObject(i);																	
														
				list.add(parseNote(obj));
			}
			
			return list;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return new ArrayList<GeoNode>();
		}	
		
	}
	
	private Note parseNote (JSONObject obj)
	{
		
		String title, text, since;
		Double latitude, longitude, altitude, radius;		
		
		title = text = since = "";
		latitude = longitude = altitude = radius = -1.0;
		Integer id = -1;
		
		try {			
			
			if (obj.has("id"))
				id = obj.getInt("id");
			
			if (obj.has("title"))
				title = obj.getString("title");
			
			if (obj.has("text"))
				text = obj.getString("text");
			
			if (obj.has("since"))
				since = obj.getString("since");
			
			if (obj.has("position"))
			{
				JSONObject objPosition = obj.getJSONObject("position");
				
				if (objPosition.has("latitude"))
					latitude = objPosition.getDouble("latitude");
				
				if (objPosition.has("longitude"))
					longitude = objPosition.getDouble("longitude");		
				
				if (objPosition.has("altitude"))
					altitude = objPosition.getDouble("altitude");		
				
				if (objPosition.has("radius"))
					radius = objPosition.getDouble("radius");
				
			}
			
			return new Note (id,title,text,latitude,longitude, altitude, radius, since);
		
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG+"-parseNote", e.toString());
			return null;
		}
	}
	
	private ArrayList<GeoNode>  parseUsers (String str, Double distance)
	{
		 
        JSONObject json;
        
        ArrayList<GeoNode> list = new ArrayList<GeoNode>();
        
        try {
			json = new JSONObject(str);
			lastCode = json.getInt("code");
							
			if (lastCode != 200)
				return null;
			
			JSONArray array;

			JSONObject photos = json.getJSONObject("results");
			array = photos.getJSONArray("users");

			Log.e("parseUsers: ",String.valueOf(array.length()));
			
			for (int i = 0; i < array.length(); i++) 
			{ 
				
				User user = (User) parseUser (array.getJSONObject(i));			
				
				if (user.getId() == mUser.getId())
					continue;
				
				list.add(user);
				
			}
			
			return list;
			
		} catch (JSONException e) {	
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}
	}
	
	
	private GeoNode  parseUser (JSONObject obj)
	{
		String username = "", name = "", lastName ="", status="", status_since="", since = "";
		Double latitude, longitude, altitude, radius;
		Integer id = null;
		String country = null, birthDay=null;
		Integer postCode = null;
		Integer avatarId = null;
		String avatarUrl = null;
		
		try
		{
			latitude = longitude = altitude = radius = -1.0;

			if (obj.has("id"))
				id = obj.getInt("id");
			
			if (obj.has("name"))
				name = obj.getString("name");	
			
			if (obj.has("last_name"))
				lastName = obj.getString("last_name");
			
			if (obj.has("username"))
				username = obj.getString("username");				
			
			if (obj.has("since"))
				since = obj.getString("since");	
			
			JSONObject jsonStatus = obj.getJSONObject("status");
			status = jsonStatus.getString("message");
			
			if (obj.has("since"))
				status_since = jsonStatus.getString("since");
								
			if (obj.has("position"))
			{
				JSONObject jsonPosition = obj.getJSONObject("position");
				latitude = jsonPosition.getDouble("latitude");
				longitude = jsonPosition.getDouble("longitude");
				altitude = jsonPosition.getDouble("altitude");
				
				if (obj.has("radius"))
					radius = jsonPosition.getDouble("radius");	
				if (obj.has("country"))
					country = jsonPosition.getString("country");
				if (obj.has("post_code"))
					postCode = jsonPosition.getInt("post_code");				
			}
			if (obj.has("birthday"))
				birthDay = obj.getString("birthday");
			
			if (obj.has("avatar"))
			{
				JSONObject jsonPosition = obj.getJSONObject("avatar");
				
				avatarId = jsonPosition.getInt("photo_id");
				avatarUrl = jsonPosition.getString("photo_url");
			}
			
			
			return new User(id,name,lastName,username,null,status,latitude,longitude,altitude, 
					radius, since, country,postCode,birthDay,null, avatarId, avatarUrl);
			
		} catch (JSONException e) {	
			
			lastCode = 500;
			lastMsg = "Error in json parsed: " + e.getMessage();
			Log.e(TAG, e.toString());
			return null;
		}
	}
	
	public static void allowAllSSL(){
		
		javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){

			public boolean verify(String hostname, SSLSession session) {
				// TODO Auto-generated method stub
				return true;
			}
			
		});
		
		javax.net.ssl.SSLContext context = null;
		
		if(trustManagers==null){
			trustManagers = new javax.net.ssl.TrustManager[]{new _FakeX509TrustManager()};
		}
		
		try{
			context = javax.net.ssl.SSLContext.getInstance("TLS");
			context.init(null, trustManagers, new SecureRandom());
			
		}catch(NoSuchAlgorithmException e){
			Log.e("allowAllSSL", e.toString());
		}catch(KeyManagementException e){
			Log.e("allowAllSSL", e.toString());
		}
		
		javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
		
	}
	
	public static class _FakeX509TrustManager implements javax.net.ssl.X509TrustManager{
		
		private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
		
		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub
			
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub
			
		}
		
		public boolean isClientTrusted(X509Certificate[] chain){
			return true;
		}
		
		public boolean isServerTrusted(X509Certificate[] chain){
			return true;
		}
		
		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return _AcceptedIssuers;
		}
		
	}
	
}
